home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 3: CDPD 3 / Almathera Ten on Ten - Disc 3: CDPD3.iso / fish / 676-700 / 681 / term / source.lha / termBuffer.c < prev    next >
C/C++ Source or Header  |  1992-05-15  |  38KB  |  1,598 lines

  1. /*
  2. **    $Id: termBuffer.c,v 1.8 92/05/15 22:24:49 olsen Sta Locker: olsen $
  3. **    $Revision: 1.8 $
  4. **    $Date: 92/05/15 22:24:49 $
  5. **
  6. **    Support routines for the log book (review buffer)
  7. **
  8. **    Copyright © 1990-1992 by Olaf `Olsen' Barthel & MXM
  9. **        All Rights Reserved
  10. */
  11.  
  12. #include "termGlobal.h"
  13.  
  14.     /* Some private data (render info & window). */
  15.  
  16. STATIC struct Window    *BufferWindow;
  17. STATIC struct Screen    *BufferScreen;
  18.  
  19. STATIC struct RastPort    *BPort;
  20. STATIC APTR         BufferVisualInfo;
  21.  
  22. STATIC LONG         BufLine,BufCols;
  23.  
  24. STATIC BYTE         MarkedArea;
  25.  
  26. STATIC BYTE         BufferTerminated;
  27.  
  28. enum    {    MEN_SEARCH,MEN_REPEAT,MEN_GOTO,MEN_CLEARBUF,MEN_CLOSEBUF,MEN_QUITBUF };
  29.  
  30. enum    {    GAD_SCROLL };
  31.  
  32. STATIC struct NewMenu BufferMenu[] =
  33. {
  34.     { NM_TITLE, NULL,         0 , 0, 0, (APTR)0},
  35.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_SEARCH},
  36.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_REPEAT},
  37.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  38.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_GOTO},
  39.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  40.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_CLEARBUF},
  41.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_CLOSEBUF},
  42.     {  NM_ITEM, NM_BARLABEL,     0 , 0, 0, (APTR)0},
  43.     {  NM_ITEM, NULL,         0 , 0, 0, (APTR)MEN_QUITBUF},
  44.     { NM_END, 0,             0 , 0, 0, (APTR)0}
  45. };
  46.  
  47.     /* AllocString(UBYTE *String,WORD Len):
  48.      *
  49.      +    Allocate space for a string.
  50.      */
  51.  
  52. STATIC UBYTE *
  53. AllocString(UBYTE *String,WORD Len)
  54. {
  55.     ULONG *Mem;
  56.  
  57.     if(Mem = AllocMem(sizeof(ULONG) + Len,MEMF_ANY))
  58.     {
  59.         *Mem++ = Len;
  60.  
  61.         CopyMem(String,Mem,Len);
  62.  
  63.         String = (UBYTE *)Mem;
  64.  
  65.         return(String);
  66.     }
  67.  
  68.     return(NULL);
  69. }
  70.  
  71.     /* FreeString(UBYTE *String):
  72.      *
  73.      *    Free the space occupied by a string.
  74.      */
  75.  
  76. STATIC VOID
  77. FreeString(UBYTE *String)
  78. {
  79.     FreeMem(&((ULONG *)String)[-1],((ULONG *)String)[-1] + sizeof(ULONG));
  80. }
  81.  
  82.     /* AddLine(UBYTE *Line,LONG Size):
  83.      *
  84.      *    Add a line to the display buffer.
  85.      */
  86.  
  87. VOID
  88. AddLine(UBYTE *Line,LONG Size)
  89. {
  90.     if(!BufferClosed)
  91.     {
  92.         ULONG Signals = 0;
  93.  
  94.             /* Is the buffer array initialized? */
  95.  
  96.         if(BufferLines)
  97.         {
  98.                 /* Pick up the global access semaphore
  99.                  * (two tasks are sharing the data).
  100.                  */
  101.  
  102.             ObtainSemaphore(BufferSemaphore);
  103.  
  104.                 /* Check for limit. */
  105.  
  106.             if(Config . MaxLogBuffSize && BufferSpace >= Config . MaxLogBuffSize)
  107.                 goto Wrap;
  108.  
  109.                 /* We've reached the last line in the buffer. */
  110.  
  111.             if(Lines == MaxLines)
  112.             {
  113.                 UBYTE **MoreBuffer;
  114.                 LONG i;
  115.  
  116.                     /* Allocate space for some more lines. */
  117.  
  118.                 if(MoreBuffer = (UBYTE **)AllocVec((MaxLines + 100) * sizeof(UBYTE *),MEMF_ANY|MEMF_CLEAR))
  119.                 {
  120.                         /* Copy the old lines to the new
  121.                          * buffer.
  122.                          */
  123.  
  124.                     for(i = 0 ; i < Lines ; i++)
  125.                         MoreBuffer[i] = BufferLines[i];
  126.  
  127.                         /* Free the old lines. */
  128.  
  129.                     FreeVec(BufferLines);
  130.  
  131.                         /* Set the new buffer. */
  132.  
  133.                     MaxLines += 100;
  134.  
  135.                     BufferLines = MoreBuffer;
  136.                 }
  137.                 else
  138.                 {
  139.                         /* We couldn't get enough memory
  140.                          * to extend the number of lines
  141.                          * in the buffer, so we'll have
  142.                          * to wrap the contents of the
  143.                          * buffer around.
  144.                          */
  145.  
  146.                     if(Lines)
  147.                     {
  148. Wrap:                        BufferSpace -= ((ULONG *)BufferLines[0])[-1];
  149.  
  150.                         FreeString(BufferLines[0]);
  151.  
  152.                         for(i = 1 ; i < MaxLines ; i++)
  153.                             BufferLines[i - 1] = BufferLines[i];
  154.  
  155.                         Lines--;
  156.  
  157.                             /* Tell the buffer task to
  158.                              * refresh the display.
  159.                              */
  160.  
  161.                         Signals = SIGBREAKF_CTRL_F;
  162.                     }
  163.                 }
  164.             }
  165.  
  166.                 /* Allocate a new line and copy the buffer contents
  167.                  * into it.
  168.                  */
  169.  
  170.             if(BufferLines[Lines] = AllocString(Line,Size))
  171.             {
  172.                 Lines++;
  173.  
  174.                 BufferSpace += Size;
  175.                         }
  176.  
  177.             ReleaseSemaphore(BufferSemaphore);
  178.  
  179.                 /* Tell the buffer task to update the display. */
  180.  
  181.             if(!Signals)
  182.             {
  183.                 Signals = SIGBREAKF_CTRL_E;
  184.  
  185.                 UpdateReview(FALSE);
  186.             }
  187.             else
  188.                 UpdateReview(TRUE);
  189.  
  190.             if(BufferProcess)
  191.                 Signal(BufferProcess,Signals);
  192.         }
  193.     }
  194. }
  195.  
  196.     /* ClearBuffer():
  197.      *
  198.      *    Clear the current display buffer and flush the contents
  199.      *    of the buffered capture file handles.
  200.      */
  201.  
  202. VOID
  203. ClearBuffer()
  204. {
  205.     LONG i;
  206.  
  207.     if(BufferProcess)
  208.     {
  209.         Signal(BufferProcess,SIGBREAKF_CTRL_C);
  210.  
  211.         Wait(SIGBREAKF_CTRL_C);
  212.     }
  213.  
  214.     if(PrinterCapture)
  215.         Flush(PrinterCapture);
  216.  
  217.         /* Free the contents of the display buffer. */
  218.  
  219.     if(BufferLines)
  220.     {
  221.         for(i = 0 ; i < Lines ; i++)
  222.         {
  223.             if(BufferLines[i])
  224.                 FreeString(BufferLines[i]);
  225.         }
  226.  
  227.         FreeVec(BufferLines);
  228.  
  229.         BufferLines = NULL;
  230.  
  231.         Lines = 0;
  232.  
  233.         MaxLines = 100;
  234.  
  235.         BufferLines = (UBYTE **)AllocVec(MaxLines * sizeof(UBYTE *),MEMF_ANY|MEMF_CLEAR);
  236.     }
  237.  
  238.     BufferSpace = 0;
  239. }
  240.  
  241.     /* StoreBuffer(APTR Buffer,LONG Size):
  242.      *
  243.      *    Store data in the display buffer.
  244.      */
  245.  
  246. VOID
  247. StoreBuffer(APTR Buffer,LONG Size)
  248. {
  249.     STATIC UBYTE     LineBuffer[200];
  250.     STATIC LONG      BufferCount = 0;
  251.  
  252.     UBYTE        *CharBuffer = Buffer;
  253.     LONG         i;
  254.  
  255.     for(i = 0 ; i < Size ; i++)
  256.     {
  257.             /* Look which char we are to handle. */
  258.  
  259.         switch(CharBuffer[i])
  260.         {
  261.                 /* Ignore the following characters. */
  262.  
  263.             case FFD:
  264.             case BEL:
  265.             case DEL:
  266.             case VTB:
  267.             case XON:
  268.             case XOF:    continue;
  269.  
  270.                 /* Move the cursor to the next tab
  271.                  * stop.
  272.                  */
  273.  
  274.             case TAB:    if(BufferCount + 8 < LastColumn)
  275.                     {
  276.                         strcpy(&LineBuffer[BufferCount],"        ");
  277.  
  278.                         BufferCount += 8;
  279.  
  280.                         break;
  281.                     }
  282.  
  283.                     continue;
  284.  
  285.                 /* Move the cursor one step back. */
  286.  
  287.             case BKS:    if(BufferCount)
  288.                         BufferCount--;
  289.  
  290.                     continue;
  291.  
  292.                 /* Ignore carriage return (should have been
  293.                  * filtered already).
  294.                  */
  295.  
  296.             case RET:    continue;
  297.  
  298.                 /* Terminate the current line. */
  299.  
  300.             case ENT:    AddLine(LineBuffer,BufferCount);
  301.  
  302.                     BufferCount = 0;
  303.                     continue;
  304.  
  305.                 /* Stuff the character into the buffer. */
  306.  
  307.             default:    LineBuffer[BufferCount++] = CharBuffer[i];
  308.                     break;
  309.         }
  310.  
  311.             /* The line is full, add it to the display buffer. */
  312.  
  313.         if(BufferCount > LastColumn || BufferCount == sizeof(LineBuffer))
  314.         {
  315.             AddLine(LineBuffer,BufferCount);
  316.  
  317.             BufferCount = 0;
  318.         }
  319.     }
  320. }
  321.  
  322.     /* FlushIMsg(struct Window *Window):
  323.      *
  324.      +    Clear the MsgPort of a window.
  325.      */
  326.  
  327. STATIC VOID
  328. FlushIMsg(struct Window *Window)
  329. {
  330.     struct IntuiMessage *Massage;
  331.  
  332.     while(Massage = GT_GetIMsg(Window -> UserPort))
  333.         GT_ReplyIMsg(Massage);
  334. }
  335.  
  336.     /* CreateAllGadgets():
  337.      *
  338.      *    Create all the gadgets required by the
  339.      *    buffer screen (i.e. the scroller gadget).
  340.      */
  341.  
  342. STATIC struct Gadget *
  343. CreateAllGadgets(struct Gadget **GadgetArray,struct Gadget **GadgetList)
  344. {
  345.     struct Gadget        *Gadget;
  346.     struct NewGadget     NewGadget;
  347.  
  348.     memset(&NewGadget,0,sizeof(struct NewGadget));
  349.  
  350.     if(Gadget = CreateContext(GadgetList))
  351.     {
  352.         NewGadget . ng_GadgetText    = "";
  353.         NewGadget . ng_Width        = 16;
  354.         NewGadget . ng_Height        = BufferWindow -> Height;
  355.         NewGadget . ng_TextAttr        = &DefaultFont;
  356.         NewGadget . ng_VisualInfo    = BufferVisualInfo;
  357.         NewGadget . ng_GadgetID        = 0;
  358.         NewGadget . ng_LeftEdge        = BufferWindow -> Width - 16;
  359.         NewGadget . ng_TopEdge        = 0;
  360.  
  361.         GadgetArray[0] = Gadget = CreateGadget(SCROLLER_KIND,Gadget,&NewGadget,
  362.             GTSC_Arrows,    (Config . DisplayMode & LACE) ? 16 : 8,
  363.             PGA_Freedom,    LORIENT_VERT,
  364.         TAG_DONE);
  365.     }
  366.  
  367.     return(Gadget);
  368. }
  369.  
  370.     /* GetSearchString(UBYTE *Buffer):
  371.      *
  372.      *    Prompt user for a string to search the buffer for.
  373.      */
  374.  
  375. STATIC BYTE
  376. GetSearchString(UBYTE *Buffer)
  377. {
  378.     struct Gadget    *GadgetList = NULL;
  379.     struct Gadget    *GadgetArray[4];
  380.     struct Window    *PanelWindow;
  381.     LONG         Width;
  382.     UBYTE         OtherBuffer[256];
  383.     BYTE         Success = FALSE;
  384.  
  385.     strcpy(OtherBuffer,Buffer);
  386.  
  387.     if(CreateAllGetsGadgets(FALSE,OtherBuffer,LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),&Width,&GadgetArray[0],&GadgetList,BufferVisualInfo,BufferScreen -> WBorTop + BufferScreen -> Font -> ta_YSize + 1,BufferScreen))
  388.     {
  389.         if(PanelWindow = OpenWindowTags(NULL,
  390.             WA_Width,    Width,
  391.             WA_Height,    58,
  392.  
  393.             WA_Left,    (BufferScreen -> Width - Width) >> 1,
  394.             WA_Top,        (BufferScreen -> Height - 56) >> 1,
  395.  
  396.             WA_Activate,    TRUE,
  397.             WA_DragBar,    TRUE,
  398.             WA_DepthGadget,    TRUE,
  399.             WA_CloseGadget,    TRUE,
  400.             WA_RMBTrap,    TRUE,
  401.             WA_CustomScreen,BufferScreen,
  402.  
  403.             WA_IDCMP,    IDCMP_ACTIVEWINDOW | IDCMP_CLOSEWINDOW | IDCMP_VANILLAKEY | IDCMP_GADGETDOWN | BUTTONIDCMP | STRINGIDCMP,
  404.  
  405.             WA_Title,    LocaleString(MSG_TERMBUFFER_ENTER_SEARCH_STRING_TXT),
  406.         TAG_DONE))
  407.         {
  408.             struct IntuiMessage    *Massage;
  409.             ULONG             Class,Code;
  410.             struct Gadget        *Gadget;
  411.             BYTE             Terminated = FALSE;
  412.             ULONG             SignalSet;
  413.  
  414.             AddGList(PanelWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  415.             RefreshGList(GadgetList,PanelWindow,NULL,(UWORD)-1);
  416.             GT_RefreshWindow(PanelWindow,NULL);
  417.  
  418.             ActiveGadget = NULL;
  419.  
  420.             while(!Terminated)
  421.             {
  422.                 SignalSet = Wait((1 << PanelWindow -> UserPort -> mp_SigBit) | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_C);
  423.  
  424.                 if(SignalSet & SIGBREAKF_CTRL_D)
  425.                     BumpWindow(PanelWindow);
  426.  
  427.                 if(SignalSet & SIGBREAKF_CTRL_C)
  428.                 {
  429.                     BufferTerminated = TRUE;
  430.  
  431.                     Terminated = TRUE;
  432.                 }
  433.  
  434.                 if(SignalSet & (1 << PanelWindow -> UserPort -> mp_SigBit))
  435.                 {
  436.                     while(!Terminated && (Massage = (struct IntuiMessage *)GT_GetIMsg(PanelWindow -> UserPort)))
  437.                     {
  438.                         Class    = Massage -> Class;
  439.                         Code    = Massage -> Code;
  440.                         Gadget    = (struct Gadget *)Massage -> IAddress;
  441.  
  442.                         GT_ReplyIMsg(Massage);
  443.  
  444.                         if(Class == IDCMP_VANILLAKEY)
  445.                             KeySelect(GadgetArray,3,Code,PanelWindow,&Gadget,&Class,&Code);
  446.  
  447.                         if(Class == IDCMP_GADGETDOWN)
  448.                         {
  449.                             if((Gadget -> GadgetType & GTYP_GTYPEMASK) == GTYP_STRGADGET)
  450.                                 ActiveGadget = Gadget;
  451.                         }
  452.  
  453.                         if(Class == IDCMP_ACTIVEWINDOW && ActiveGadget)
  454.                             ActivateGadget(ActiveGadget,PanelWindow,NULL);
  455.  
  456.                         if(Class == IDCMP_CLOSEWINDOW)
  457.                             Terminated = TRUE;
  458.  
  459.                         if(Class == IDCMP_GADGETUP)
  460.                         {
  461.                             switch(Gadget -> GadgetID)
  462.                             {
  463.                                 case 0: if(Code != '\t' && ((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer[0])
  464.                                     {
  465.                                         strcpy(Buffer,GT_STRING(GadgetArray[0]));
  466.  
  467.                                         Success = TRUE;
  468.  
  469.                                         Terminated = TRUE;
  470.                                     }
  471.  
  472.                                     break;
  473.  
  474.                                 case 1:    if(((struct StringInfo *)GadgetArray[0] -> SpecialInfo) -> Buffer[0])
  475.                                     {
  476.                                         strcpy(Buffer,GT_STRING(GadgetArray[0]));
  477.  
  478.                                         Success = TRUE;
  479.  
  480.                                         Terminated = TRUE;
  481.                                     }
  482.  
  483.                                     break;
  484.  
  485.                                 case 3:    Terminated = TRUE;
  486.                                     break;
  487.                             }
  488.                         }
  489.                     }
  490.                 }
  491.             }
  492.  
  493.             RemoveGList(PanelWindow,GadgetList,(UWORD)-1);
  494.  
  495.             CloseWindow(PanelWindow);
  496.         }
  497.     }
  498.  
  499.     FreeGadgets(GadgetList);
  500.  
  501.     return(Success);
  502. }
  503.  
  504.     /* PrintLine(UBYTE *Buffer,LONG LineNumber):
  505.      *
  506.      *    Print a line at a given line number in the displayed area.
  507.      */
  508.  
  509. STATIC VOID
  510. PrintLine(UBYTE *Buffer,LONG LineNumber)
  511. {
  512.     WORD Length = ((ULONG *)Buffer)[-1];
  513.  
  514.         /* The line doesn't exactly fill the displayed line,
  515.          * so erase the remaining columns.
  516.          */
  517.  
  518.     if(Length < BufCols)
  519.     {
  520.         SetAPen(BPort,0);
  521.  
  522.         RectFill(BPort,Length << 3,LineNumber << 3,(BufCols << 3) - 1,((LineNumber + 1) << 3) - 1);
  523.  
  524.         SetAPen(BPort,1);
  525.     }
  526.  
  527.         /* Print the text. */
  528.  
  529.     if(Length)
  530.     {
  531.         Move(BPort,0,(LineNumber << 3) + 6);
  532.  
  533.         if(Length > BufCols)
  534.             Text(BPort,Buffer,BufCols);
  535.         else
  536.             Text(BPort,Buffer,Length);
  537.     }
  538. }
  539.  
  540.     /* RedrawScreen(LONG FirstLine):
  541.      *
  542.      *    Redraw the contents of the entire screen and return the
  543.      *    number of lines actually drawn.
  544.      */
  545.  
  546. STATIC LONG
  547. RedrawScreen(LONG FirstLine)
  548. {
  549.     LONG i,Last,Line = 0;
  550.  
  551.         /* Determine last line to display. */
  552.  
  553.     if((Last = FirstLine + BufLine) >= Lines)
  554.         Last = Lines;
  555.  
  556.         /* Obtain the access semaphore and display the single
  557.          * lines.
  558.          */
  559.  
  560.     ObtainSemaphore(BufferSemaphore);
  561.  
  562.     for(i = FirstLine ; i < Last ; i++)
  563.         PrintLine(BufferLines[i],Line++);
  564.  
  565.     ReleaseSemaphore(BufferSemaphore);
  566.  
  567.         /* We didn't fill the whole screen, so clear the rest. */
  568.  
  569.     if(Line < BufLine)
  570.     {
  571.         SetAPen(BPort,0);
  572.  
  573.         RectFill(BPort,0,Line << 3,BufferWindow -> Width - (1 + 16),BufferWindow -> Height - 1);
  574.  
  575.         SetAPen(BPort,1);
  576.     }
  577.  
  578.     return(Line);
  579. }
  580.  
  581.     /* MarkArea(WORD Column,WORD Line,WORD Length):
  582.      *
  583.      *    Mark an area in the term Buffer window.
  584.      */
  585.  
  586. STATIC VOID
  587. MarkArea(WORD Column,WORD Line,WORD Length)
  588. {
  589.     STATIC WORD OldColumn = -1,OldLine = -1,OldLength = -1;
  590.  
  591.     if(OldColumn != Column || OldLine != Line || OldLength != Length)
  592.     {
  593.         if(OldColumn != -1)
  594.             ClipBlit(BPort,0,0,BPort,OldColumn << 3,OldLine << 3,OldLength << 3,8,0x50);
  595.  
  596.         MarkedArea = TRUE;
  597.  
  598.         if(Column != -1)
  599.             ClipBlit(BPort,0,0,BPort,Column << 3,Line << 3,Length << 3,8,0x50);
  600.         else
  601.             MarkedArea = FALSE;
  602.     }
  603.  
  604.     OldColumn    = Column;
  605.     OldLine        = Line;
  606.     OldLength    = Length;
  607. }
  608.  
  609.     /* Search():
  610.      *
  611.      *    String search function, based on the Boyer-Moore search
  612.      *    algorithm.
  613.      */
  614.  
  615. STATIC LONG
  616. Search(UBYTE *Pattern,LONG *FoundX,LONG *FoundY,LONG *SaveX)
  617. {
  618.     UBYTE    Distance[256],NewPattern[256],PatternWidth,SearchWidth;
  619.     LONG    LineNumber = -1,i;
  620.     WORD    j,k,l;
  621.  
  622.         /* Determine length of search pattern. */
  623.  
  624.     PatternWidth = strlen(Pattern);
  625.  
  626.         /* Convert search pattern to upper cse. */
  627.  
  628.     for(i = 0 ; i <= PatternWidth ; i++)
  629.         NewPattern[i] = ToUpper(Pattern[i]);
  630.  
  631.         /* Create distance table. */
  632.  
  633.     for(i = 0 ; i < 256 ; i++)
  634.         Distance[i] = PatternWidth;
  635.  
  636.     for(i = 0 ; i < PatternWidth - 1 ; i++)
  637.         Distance[NewPattern[i]] = PatternWidth - i - 1;
  638.  
  639.         /* Run down the buffer. */
  640.  
  641.     for(i = *FoundY ; i < Lines ; i++)
  642.     {
  643.             /* Is there anything to search for? */
  644.  
  645.         if(SearchWidth = ((ULONG *)BufferLines[i])[-1])
  646.         {
  647.                 /* Casteth the magick spelle of
  648.                  * Boyer-Moore...
  649.                  */
  650.  
  651.             j = PatternWidth;
  652.  
  653.             do
  654.             {
  655.                 k = PatternWidth;
  656.                 l = j;
  657.  
  658.                 do
  659.                 {
  660.                     k--;
  661.                     l--;
  662.                 }
  663.                 while(k >= 0 && NewPattern[k] == ToUpper(BufferLines[i][l]));
  664.  
  665.                 j += Distance[ToUpper(BufferLines[i][j - 1])];
  666.             }
  667.             while(k >= 0 && j <= SearchWidth);
  668.  
  669.                 /* Found first occurence, set up the
  670.                  * data and quit.
  671.                  */
  672.  
  673.             if(k < 0)
  674.             {
  675.                 *FoundX    = l + 1;
  676.                 *FoundY    = LineNumber = i;
  677.  
  678.                 *SaveX    = l + 1;
  679.  
  680.                 if(BufferLines[i][*FoundX + 1])
  681.                     *FoundX++;
  682.                 else
  683.                 {
  684.                     if(*FoundY - 1 < Lines)
  685.                     {
  686.                         *FoundX = 0;
  687.                         *FoundY++;
  688.                     }
  689.                 }
  690.  
  691.                 return(LineNumber);
  692.             }
  693.             else
  694.                 *FoundX = 0;
  695.         }
  696.     }
  697.  
  698.     return(LineNumber);
  699. }
  700.  
  701.     /* BufferServer():
  702.      *
  703.      *    Asynchronous task to display the data stored in the
  704.      *    scrollback display buffer.
  705.      */
  706.  
  707. VOID __saveds
  708. BufferServer()
  709. {
  710.     struct ColorSpec     ColorSpec[3];
  711.  
  712.     ULONG             SignalSet;
  713.  
  714.     struct IntuiMessage    *Massage;
  715.     ULONG             Class,Code,Qualifier;
  716.     UBYTE             Char,LastChar = 0;
  717.  
  718.     LONG             CurrentLine,DisplayedLines;
  719.  
  720.     UBYTE             PercentBuffer[80];
  721.  
  722.     struct Menu        *BufferMenuStrip;
  723.  
  724.     STATIC UBYTE         SearchBuffer[256];
  725.     LONG             LineNumber,SaveX,FoundX = 0,FoundY = 0;
  726.     ULONG             DisplayMode;
  727.  
  728.     struct Rectangle     DisplayClip;
  729.  
  730.     UWORD             SomeColour;
  731.  
  732.     struct Gadget        *GadgetList = NULL;
  733.     struct Gadget        *GadgetArray[1];
  734.  
  735.     BufferTerminated = FALSE;
  736.  
  737.         /* Set up the startup colours for our buffer screen. */
  738.  
  739.     ColorSpec[0] . ColorIndex    = 0;
  740.     ColorSpec[0] . Red        = (Config . Colours[0] >> 8) & 0xF;
  741.     ColorSpec[0] . Green        = (Config . Colours[0] >> 4) & 0xF;
  742.     ColorSpec[0] . Blue        = (Config . Colours[0]     ) & 0xF;
  743.  
  744.     switch(Config . ColourMode)
  745.     {
  746.         case COLOUR_EIGHT:    SomeColour = Config . Colours[7];
  747.                     break;
  748.  
  749.         case COLOUR_SIXTEEN:    SomeColour = Config . Colours[15];
  750.                     break;
  751.  
  752.         case COLOUR_AMIGA:
  753.         default:        SomeColour = Config . Colours[1];
  754.                     break;
  755.     }
  756.  
  757.     ColorSpec[1] . ColorIndex    = 1;
  758.     ColorSpec[1] . Red        = (SomeColour >> 8) & 0xF;
  759.     ColorSpec[1] . Green        = (SomeColour >> 4) & 0xF;
  760.     ColorSpec[1] . Blue        = (SomeColour     ) & 0xF;
  761.  
  762.     ColorSpec[2] . ColorIndex    = -1;
  763.  
  764.         /* We'll use a fixed screen width, only the
  765.          * height is adapted from the main screen.
  766.          */
  767.  
  768.     DisplayMode = Config . DisplayMode;
  769.  
  770.         /* Inquire the text overscan dimensions. */
  771.  
  772.     if(QueryOverscan(DisplayMode,&DisplayClip,OSCAN_TEXT))
  773.     {
  774.             /* Centre the buffer screen. */
  775.  
  776.         if(DisplayClip . MaxX - DisplayClip . MinX + 1 > 640 + 16)
  777.         {
  778.             WORD Differ = ((DisplayClip . MaxX - DisplayClip . MinX + 1) - (640 + 16)) >> 1;
  779.  
  780.             DisplayClip . MinX += Differ;
  781.             DisplayClip . MaxX -= Differ;
  782.         }
  783.  
  784.             /* Open a single bitplane clone of the main screen. */
  785.  
  786.         if(BufferScreen = (struct Screen *)OpenScreenTags(NULL,
  787.             SA_Title,    LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT),
  788.             SA_Depth,    1,
  789.             SA_DClip,    &DisplayClip,
  790.             SA_DisplayID,    DisplayMode,
  791.             SA_Font,    &DefaultFont,
  792.             SA_Behind,    TRUE,
  793.             SA_AutoScroll,    TRUE,
  794.             SA_Colors,    ColorSpec,
  795.         TAG_END))
  796.         {
  797.             if(BufferVisualInfo = GetVisualInfo(BufferScreen,TAG_DONE))
  798.             {
  799.                 LocalizeMenu(BufferMenu,MSG_TERMBUFFER_PROJECT_MEN);
  800.  
  801.                 if(BufferMenuStrip = CreateMenus(BufferMenu,
  802.                     GTMN_FrontPen, 0,
  803.                 TAG_DONE))
  804.                 {
  805.                     if(LayoutMenus(BufferMenuStrip,BufferVisualInfo,
  806.                         GTMN_TextAttr,&DefaultFont,
  807.                     TAG_DONE))
  808.                     {
  809.                         WORD TitleOffset;
  810.  
  811.                         TitleOffset = (strlen(LocaleString(MSG_TERMBUFFER_TERM_BUFFER_TXT)) + 1) * 8 + 4;
  812.  
  813.                             /* Open a cute window on our buffer screen. */
  814.  
  815.                         if(BufferWindow = OpenWindowTags(NULL,
  816.                             WA_Top,        BufferScreen -> BarHeight + 2,
  817.                             WA_Left,    0,
  818.                             WA_Width,    BufferScreen -> Width,
  819.                             WA_Height,    BufferScreen -> Height - (Screen -> BarHeight + 2),
  820.                             WA_Backdrop,    TRUE,
  821.                             WA_Borderless,    TRUE,
  822.                             WA_SmartRefresh,FALSE,
  823.                             WA_CustomScreen,BufferScreen,
  824.                             WA_RMBTrap,    TRUE,
  825.                             WA_RptQueue,    1,
  826.                             WA_IDCMP,    IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_MOUSEMOVE | IDCMP_MENUPICK | IDCMP_INACTIVEWINDOW | ARROWIDCMP | SCROLLERIDCMP,
  827.                         TAG_DONE))
  828.                         {
  829.                             if(CreateAllGadgets(&GadgetArray[0],&GadgetList))
  830.                             {
  831.                                     /* Signal our father process that
  832.                                      * we're running.
  833.                                      */
  834.  
  835.                                 Signal(ThisProcess,SIGBREAKF_CTRL_C);
  836.  
  837.                                 SetMenuStrip(BufferWindow,BufferMenuStrip);
  838.  
  839.                                 AddGList(BufferWindow,GadgetList,(UWORD)-1,(UWORD)-1,NULL);
  840.                                 RefreshGList(GadgetList,BufferWindow,NULL,(UWORD)-1);
  841.                                 GT_RefreshWindow(BufferWindow,NULL);
  842.  
  843. Restart:                                /* Set the IBM font if necessary. */
  844.  
  845.                                 BPort = BufferWindow -> RPort;
  846.  
  847.                                 if(Config . Font == FONT_IBM && IBM)
  848.                                     SetFont(BPort,IBM);
  849.  
  850.                                     /* Determine maximum dimensions of
  851.                                      * the buffer screen (in rows and
  852.                                      * columns).
  853.                                      */
  854.  
  855.                                 BufCols    = (BufferWindow -> Width - 16) >> 3;
  856.                                 BufLine    = BufferWindow -> Height >> 3;
  857.  
  858.                                     /* Bring the screen to the front. */
  859.  
  860.                                 BumpWindow(BufferWindow);
  861.  
  862.                                     /* Set the drawing pens for the window. */
  863.  
  864.                                 SetAPen(BPort,1);
  865.                                 SetBPen(BPort,0);
  866.                                 SetDrMd(BPort,JAM2);
  867.  
  868.                                     /* Initial creation of the buffer display. */
  869.  
  870.                                 DisplayedLines = RedrawScreen(CurrentLine = 0);
  871.  
  872.                                 GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  873.                                     GTSC_Top,    0,
  874.                                     GTSC_Total,    Lines,
  875.                                     GTSC_Visible,    BufLine,
  876.                                 TAG_DONE);
  877.  
  878.                                 BufferWindow -> Flags &= ~WFLG_RMBTRAP;
  879.  
  880.                                 while(!BufferTerminated)
  881.                                 {
  882.                                         /* Show where we are. */
  883.  
  884.                                     if(Lines)
  885.                                     {
  886.                                         extern APTR LocaleBase;
  887.  
  888.                                         SetAPen(BufferScreen -> BarLayer -> rp,0);
  889.                                         SetBPen(BufferScreen -> BarLayer -> rp,1);
  890.                                         SetDrMd(BufferScreen -> BarLayer -> rp,JAM2);
  891.  
  892.                                         if(LocaleBase)
  893.                                             SPrintf(PercentBuffer,"%lD/%lD (%ld%%)                  ",CurrentLine,Lines > BufLine ? Lines - BufLine : 0,(100 * (CurrentLine + DisplayedLines)) / Lines);
  894.                                         else
  895.                                             SPrintf(PercentBuffer,"%ld/%ld (%ld%%)                  ",CurrentLine,Lines > BufLine ? Lines - BufLine : 0,(100 * (CurrentLine + DisplayedLines)) / Lines);
  896.  
  897.                                         Move(BufferScreen -> BarLayer -> rp,TitleOffset,7);
  898.                                         Text(BufferScreen -> BarLayer -> rp,PercentBuffer,strlen(PercentBuffer));
  899.                                     }
  900.  
  901.                                     SignalSet = Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | SIGBREAKF_CTRL_E | SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
  902.  
  903.                                         /* Leave the town? */
  904.  
  905.                                     if(SignalSet & SIGBREAKF_CTRL_C)
  906.                                         BufferTerminated = TRUE;
  907.  
  908.                                         /* Bring our window to the front. */
  909.  
  910.                                     if(SignalSet & SIGBREAKF_CTRL_D)
  911.                                         BumpWindow(BufferWindow);
  912.  
  913.                                         /* We've got one more line in the
  914.                                          * buffer.
  915.                                          */
  916.  
  917.                                     if(SignalSet & SIGBREAKF_CTRL_E)
  918.                                     {
  919.                                         if(Lines - CurrentLine > DisplayedLines && DisplayedLines < BufLine)
  920.                                         {
  921.                                             ObtainSemaphore(BufferSemaphore);
  922.  
  923.                                             PrintLine(BufferLines[CurrentLine + DisplayedLines],DisplayedLines++);
  924.  
  925.                                             ReleaseSemaphore(BufferSemaphore);
  926.                                         }
  927.  
  928.                                         GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  929.                                             GTSC_Total,    Lines,
  930.                                             GTSC_Visible,    BufLine,
  931.                                         TAG_DONE);
  932.                                     }
  933.  
  934.                                         /* The contents of the buffer have moved
  935.                                          * up a line.
  936.                                          */
  937.  
  938.                                     if(SignalSet & SIGBREAKF_CTRL_F)
  939.                                         DisplayedLines = RedrawScreen(CurrentLine);
  940.  
  941.                                         /* Process the incoming window
  942.                                          * input.
  943.                                          */
  944.  
  945.                                     while(Massage = (struct IntuiMessage *)GT_GetIMsg(BufferWindow -> UserPort))
  946.                                     {
  947.                                         Class        = Massage -> Class;
  948.                                         Code        = Massage -> Code;
  949.                                         Qualifier    = Massage -> Qualifier;
  950.  
  951.                                             /* This hack is necessary to obtain the
  952.                                              * character codes generated for the cursor
  953.                                              * keys. A control or alternate qualifier
  954.                                              * would spoil the result (i.e. we would
  955.                                              * not get a valid key code).
  956.                                              */
  957.  
  958.                                         Massage -> Qualifier = NULL;
  959.  
  960.                                         Char = KeyConvert(Massage,NULL,NULL);
  961.  
  962.                                             /* Just in case anybody needs it... */
  963.  
  964.                                         Massage -> Qualifier = Qualifier;
  965.  
  966.                                         GT_ReplyIMsg(Massage);
  967.  
  968.                                         if(Class == IDCMP_MOUSEMOVE)
  969.                                         {
  970.                                             if(Code != CurrentLine)
  971.                                             {
  972.                                                 if(ABS(CurrentLine - Code) == 1)
  973.                                                 {
  974.                                                     Qualifier    = NULL;
  975.                                                     Class        = IDCMP_RAWKEY;
  976.  
  977.                                                     if(Code > CurrentLine)
  978.                                                         Code = CDN;
  979.                                                     else
  980.                                                         Code = CUP;
  981.  
  982.                                                     goto UseKey;
  983.                                                 }
  984.                                                 else
  985.                                                 {
  986.                                                     if(MarkedArea)
  987.                                                         MarkArea(-1,-1,-1);
  988.  
  989.                                                     DisplayedLines = RedrawScreen(CurrentLine = Code);
  990.                                                 }
  991.                                             }
  992.                                         }
  993.  
  994.                                         if(Class == IDCMP_RAWKEY)
  995.                                         {
  996.                                             if(LastChar && (Code & IECODE_UP_PREFIX))
  997.                                             {
  998.                                                 GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  999.                                                     GTSC_Top,    CurrentLine,
  1000.                                                     GTSC_Total,    Lines,
  1001.                                                     GTSC_Visible,    BufLine,
  1002.                                                 TAG_DONE);
  1003.                                             }
  1004.  
  1005.                                             if(LastChar = Char)
  1006.                                             {
  1007.                                                     /* Use the numeric keypad keys to
  1008.                                                      * move through the buffer.
  1009.                                                      */
  1010.  
  1011. UseKey:                                                if(Qualifier & IEQUALIFIER_NUMERICPAD)
  1012.                                                 {
  1013.                                                         /* Remove the numpad qualifier. */
  1014.  
  1015.                                                     Qualifier &= ~IEQUALIFIER_NUMERICPAD;
  1016.  
  1017.                                                     switch(Char - '0')
  1018.                                                     {
  1019.                                                             /* Jump to bottom. */
  1020.  
  1021.                                                         case 1: Char = CDN;
  1022.                                                             Qualifier |= IEQUALIFIER_CONTROL;
  1023.                                                             break;
  1024.  
  1025.                                                             /* Jump to top. */
  1026.  
  1027.                                                         case 7: Char = CUP;
  1028.                                                             Qualifier |= IEQUALIFIER_CONTROL;
  1029.                                                             break;
  1030.  
  1031.                                                             /* Move one page down. */
  1032.  
  1033.                                                         case 3: Char = CDN;
  1034.                                                             Qualifier |= IEQUALIFIER_LSHIFT;
  1035.                                                             break;
  1036.  
  1037.                                                             /* Move one page up. */
  1038.  
  1039.                                                         case 9: Char = CUP;
  1040.                                                             Qualifier |= IEQUALIFIER_LSHIFT;
  1041.                                                             break;
  1042.  
  1043.                                                             /* Move one line down. */
  1044.  
  1045.                                                         case 2: Char = CDN;
  1046.                                                             break;
  1047.  
  1048.                                                             /* Move one line up. */
  1049.  
  1050.                                                         case 8: Char = CUP;
  1051.                                                             break;
  1052.                                                     }
  1053.                                                 }
  1054.  
  1055.                                                     /* Check cursor keys. */
  1056.  
  1057.                                                 switch(Char)
  1058.                                                 {
  1059.                                                         /* Scroll the buffer up. */
  1060.  
  1061.                                                     case CUP:    if(Qualifier & IEQUALIFIER_CONTROL)
  1062.                                                             {
  1063.                                                                 if(MarkedArea)
  1064.                                                                     MarkArea(-1,-1,-1);
  1065.  
  1066.                                                                 if(CurrentLine)
  1067.                                                                 {
  1068.                                                                     DisplayedLines = RedrawScreen(CurrentLine = 0);
  1069.  
  1070.                                                                     GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1071.                                                                         GTSC_Top,    0,
  1072.                                                                         GTSC_Total,    Lines,
  1073.                                                                         GTSC_Visible,    BufLine,
  1074.                                                                     TAG_DONE);
  1075.                                                                 }
  1076.  
  1077.                                                                 break;
  1078.                                                             }
  1079.  
  1080.                                                             if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1081.                                                             {
  1082.                                                                 LONG NewCurrentLine;
  1083.  
  1084.                                                                 if((NewCurrentLine = CurrentLine - BufLine) < 0)
  1085.                                                                     NewCurrentLine = 0;
  1086.  
  1087.                                                                 if(MarkedArea)
  1088.                                                                     MarkArea(-1,-1,-1);
  1089.  
  1090.                                                                 if(NewCurrentLine != CurrentLine)
  1091.                                                                 {
  1092.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1093.  
  1094.                                                                     GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1095.                                                                         GTSC_Top,    CurrentLine,
  1096.                                                                         GTSC_Total,    Lines,
  1097.                                                                         GTSC_Visible,    BufLine,
  1098.                                                                     TAG_DONE);
  1099.                                                                 }
  1100.  
  1101.                                                                 break;
  1102.                                                             }
  1103.  
  1104.                                                             if(CurrentLine)
  1105.                                                             {
  1106.                                                                 if(MarkedArea)
  1107.                                                                     MarkArea(-1,-1,-1);
  1108.  
  1109.                                                                 if(DisplayedLines)
  1110.                                                                     ScrollRaster(BPort,0,-8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
  1111.  
  1112.                                                                 CurrentLine--;
  1113.  
  1114.                                                                 ObtainSemaphore(BufferSemaphore);
  1115.  
  1116.                                                                 PrintLine(BufferLines[CurrentLine],0);
  1117.  
  1118.                                                                 ReleaseSemaphore(BufferSemaphore);
  1119.  
  1120.                                                                 if(DisplayedLines < BufLine)
  1121.                                                                     DisplayedLines++;
  1122.                                                             }
  1123.  
  1124.                                                             break;
  1125.  
  1126.                                                         /* Scroll the buffer down. */
  1127.     
  1128.                                                     case CDN:    if(Qualifier & IEQUALIFIER_CONTROL)
  1129.                                                             {
  1130.                                                                 LONG NewCurrentLine;
  1131.  
  1132.                                                                 if((NewCurrentLine = Lines - BufLine) < 0)
  1133.                                                                     NewCurrentLine = 0;
  1134.  
  1135.                                                                 if(MarkedArea)
  1136.                                                                     MarkArea(-1,-1,-1);
  1137.  
  1138.                                                                 if(CurrentLine != NewCurrentLine)
  1139.                                                                 {
  1140.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1141.  
  1142.                                                                     GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1143.                                                                         GTSC_Top,    CurrentLine,
  1144.                                                                         GTSC_Total,    Lines,
  1145.                                                                         GTSC_Visible,    BufLine,
  1146.                                                                     TAG_DONE);
  1147.                                                                 }
  1148.  
  1149.                                                                 break;
  1150.                                                             }
  1151.  
  1152.                                                             if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1153.                                                             {
  1154.                                                                 LONG NewCurrentLine;
  1155.  
  1156.                                                                 if((NewCurrentLine = CurrentLine + (2 * BufLine)) > Lines)
  1157.                                                                     NewCurrentLine = Lines;
  1158.  
  1159.                                                                 if((NewCurrentLine = NewCurrentLine - BufLine) < 0)
  1160.                                                                     NewCurrentLine = 0;
  1161.  
  1162.                                                                 if(MarkedArea)
  1163.                                                                     MarkArea(-1,-1,-1);
  1164.  
  1165.                                                                 if(NewCurrentLine != CurrentLine)
  1166.                                                                 {
  1167.                                                                     DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1168.  
  1169.                                                                     GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1170.                                                                         GTSC_Top,    CurrentLine,
  1171.                                                                         GTSC_Total,    Lines,
  1172.                                                                         GTSC_Visible,    BufLine,
  1173.                                                                     TAG_DONE);
  1174.                                                                 }
  1175.  
  1176.                                                                 break;
  1177.                                                             }
  1178.  
  1179.                                                             if(CurrentLine + BufLine < Lines)
  1180.                                                             {
  1181.                                                                 if(MarkedArea)
  1182.                                                                     MarkArea(-1,-1,-1);
  1183.  
  1184.                                                                 if(DisplayedLines)
  1185.                                                                     ScrollRaster(BPort,0,8,0,0,(BufCols << 3) - 1,(DisplayedLines << 3) - 1);
  1186.  
  1187.                                                                 ObtainSemaphore(BufferSemaphore);
  1188.  
  1189.                                                                 PrintLine(BufferLines[CurrentLine + BufLine],BufLine - 1);
  1190.  
  1191.                                                                 ReleaseSemaphore(BufferSemaphore);
  1192.  
  1193.                                                                 CurrentLine++;
  1194.  
  1195.                                                                 if(DisplayedLines < BufLine)
  1196.                                                                     DisplayedLines++;
  1197.                                                             }
  1198.  
  1199.                                                             break;
  1200.  
  1201.                                                     default:    break;
  1202.                                                 }
  1203.                                             }
  1204.  
  1205.                                             continue;
  1206.                                         }
  1207.  
  1208.                                             /* User hit a mouse button. */
  1209.  
  1210.                                         if(Class == IDCMP_MOUSEBUTTONS && !(Code & IECODE_UP_PREFIX))
  1211.                                         {
  1212.                                             BYTE SkipLoop = FALSE;
  1213.                                             LONG ThisLine,ThisColumn,MyColumn,LastColumn,SomeColumn;
  1214.                                             UBYTE *TheLine;
  1215.  
  1216.                                                 /* Remember initial mouse position. */
  1217.  
  1218.                                             ThisColumn    = Massage -> MouseX >> 3;
  1219.                                             ThisLine    = Massage -> MouseY >> 3;
  1220.  
  1221.                                             if(MarkedArea)
  1222.                                                 MarkArea(-1,-1,-1);
  1223.  
  1224.                                                 /* Reasonable dimensions? */
  1225.  
  1226.                                             if(ThisLine < DisplayedLines)
  1227.                                             {
  1228.                                                     /* Find the approriate line and its length. */
  1229.  
  1230.                                                 TheLine        = BufferLines[CurrentLine + ThisLine];
  1231.                                                 LastColumn    = ((ULONG *)BufferLines[CurrentLine + ThisLine])[-1];
  1232.  
  1233.                                                     /* Resonable dimensions? */
  1234.  
  1235.                                                 if(ThisColumn < LastColumn)
  1236.                                                 {
  1237.                                                     MyColumn = ThisColumn;
  1238.  
  1239.                                                     ReportMouse(TRUE,BufferWindow);
  1240.  
  1241.                                                         /* Loop until left mouse button is release. */
  1242.  
  1243.                                                     while(!SkipLoop)
  1244.                                                     {
  1245.                                                         SignalSet = Wait(SIGBREAKF_CTRL_F | (1 << BufferWindow -> UserPort -> mp_SigBit));
  1246.  
  1247.                                                             /* Contents of the buffer has changed! */
  1248.  
  1249.                                                         if(SignalSet & SIGBREAKF_CTRL_F)
  1250.                                                         {
  1251.                                                             if(FoundY)
  1252.                                                                 FoundY--;
  1253.  
  1254.                                                             DisplayBeep(BufferScreen);
  1255.                                                             break;
  1256.                                                         }
  1257.  
  1258.                                                         while(Massage = (struct IntuiMessage *)GetMsg(BufferWindow -> UserPort))
  1259.                                                         {
  1260.                                                             Class    = Massage -> Class;
  1261.                                                             Code    = Massage -> Code;
  1262.  
  1263.                                                             ReplyMsg(Massage);
  1264.  
  1265.                                                                 /* Mouse left inner space. */
  1266.  
  1267.                                                             if(Class == IDCMP_INACTIVEWINDOW)
  1268.                                                             {
  1269.                                                                 SkipLoop = TRUE;
  1270.  
  1271.                                                                 MarkArea(-1,-1,-1);
  1272.  
  1273.                                                                 break;
  1274.                                                             }
  1275.  
  1276.                                                                 /* We're finished! */
  1277.  
  1278.                                                             if(Class == IDCMP_MOUSEBUTTONS && (Code == SELECTUP || Code == MIDDLEUP))
  1279.                                                             {
  1280.                                                                 SkipLoop = TRUE;
  1281.  
  1282.                                                                     /* Did we get a reasonable mouse
  1283.                                                                      * position?
  1284.                                                                      */
  1285.  
  1286.                                                                 if(MyColumn != ThisColumn)
  1287.                                                                 {
  1288.                                                                         /* Preserve right order of
  1289.                                                                          * numbers.
  1290.                                                                          */
  1291.  
  1292.                                                                     if(MyColumn < ThisColumn)
  1293.                                                                     {
  1294.                                                                         LONG Help;
  1295.  
  1296.                                                                         Help        = ThisColumn;
  1297.                                                                         ThisColumn    = MyColumn;
  1298.                                                                         MyColumn    = Help;
  1299.                                                                     }
  1300.  
  1301.                                                                         /* Restore the line. */
  1302.  
  1303.                                                                     if(MyColumn < LastColumn)
  1304.                                                                         LastColumn = MyColumn;
  1305.  
  1306.                                                                     MarkArea(-1,-1,-1);
  1307.  
  1308.                                                                         /* Clip the contents of the line to
  1309.                                                                          * the clipboard.
  1310.                                                                          */
  1311.  
  1312.                                                                     SaveClip(&TheLine[ThisColumn],MyColumn - ThisColumn);
  1313.  
  1314.                                                                         /* Clipping on the buffer screen is to work
  1315.                                                                          * similar to clipping on the main screen,
  1316.                                                                          * i.e. feed the line into the input
  1317.                                                                          * stream if a shift key is held down.
  1318.                                                                          */
  1319.  
  1320.                                                                     if((Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT)) || Code == MIDDLEUP)
  1321.                                                                         Signal(ThisProcess,SIG_CLIP);
  1322.                                                                 }
  1323.  
  1324.                                                                 break;
  1325.                                                             }
  1326.  
  1327.                                                                 /* The mouse has moved. */
  1328.  
  1329.                                                             if(Class == IDCMP_MOUSEMOVE)
  1330.                                                             {
  1331.                                                                 STATIC LONG OldColumn = ~0;
  1332.  
  1333.                                                                     /* Determine new mouse position. */
  1334.  
  1335.                                                                 SomeColumn = MyColumn;
  1336.  
  1337.                                                                 MyColumn = Massage -> MouseX >> 3;
  1338.  
  1339.                                                                 if((Massage -> MouseY >> 3) < ThisLine)
  1340.                                                                     MyColumn = 0;
  1341.  
  1342.                                                                 if((Massage -> MouseY >> 3) > ThisLine)
  1343.                                                                     MyColumn = LastColumn;
  1344.  
  1345.                                                                     /* Don't redraw the line if nothing
  1346.                                                                      * has changed.
  1347.                                                                      */
  1348.  
  1349.                                                                 if(OldColumn != MyColumn)
  1350.                                                                 {
  1351.                                                                     OldColumn = MyColumn;
  1352.  
  1353.                                                                         /* Reasonable position? */
  1354.  
  1355.                                                                     if(MyColumn <= LastColumn)
  1356.                                                                     {
  1357.                                                                         if(MyColumn >= 0)
  1358.                                                                         {
  1359.                                                                                 /* Highlight the selected
  1360.                                                                                  * area (invert).
  1361.                                                                                  */
  1362.  
  1363.                                                                             if(MyColumn != ThisColumn)
  1364.                                                                             {
  1365.                                                                                 if(MyColumn < ThisColumn)
  1366.                                                                                     MarkArea(MyColumn,ThisLine,ThisColumn - MyColumn);
  1367.                                                                                 else
  1368.                                                                                     MarkArea(ThisColumn,ThisLine,MyColumn - ThisColumn);
  1369.                                                                             }
  1370.                                                                         }
  1371.                                                                     }
  1372.                                                                     else
  1373.                                                                         MyColumn = SomeColumn;
  1374.                                                                 }
  1375.                                                             }
  1376.                                                         }
  1377.                                                     }
  1378.  
  1379.                                                     ReportMouse(FALSE,BufferWindow);
  1380.                                                 }
  1381.                                             }
  1382.                                         }
  1383.  
  1384.                                         if(Class == IDCMP_MENUPICK)
  1385.                                         {
  1386.                                             struct MenuItem *MenuItem;
  1387.  
  1388.                                             while(Code != MENUNULL)
  1389.                                             {
  1390.                                                 MenuItem = ItemAddress(BufferMenuStrip,Code);
  1391.  
  1392.                                                 switch((ULONG)GTMENUITEM_USERDATA(MenuItem))
  1393.                                                 {
  1394.                                                     case MEN_SEARCH:    BlockWindow(BufferWindow);
  1395.  
  1396. GetTheString:                                                            if(Lines)
  1397.                                                                 {
  1398.                                                                     if(GetSearchString(SearchBuffer))
  1399.                                                                     {
  1400.                                                                         FoundX = FoundY = 0;
  1401.  
  1402. SearchForIt:                                                                    LineNumber = -1;
  1403.  
  1404.                                                                         if(FoundY == 0 && CurrentLine != 0)
  1405.                                                                             FoundY = CurrentLine;
  1406.  
  1407.                                                                         ObtainSemaphore(BufferSemaphore);
  1408.  
  1409.                                                                         LineNumber = Search(SearchBuffer,&FoundX,&FoundY,&SaveX);
  1410.  
  1411.                                                                         ReleaseSemaphore(BufferSemaphore);
  1412.  
  1413.                                                                         if(LineNumber == -1)
  1414.                                                                         {
  1415.                                                                             BlockWindows();
  1416.  
  1417.                                                                             MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_DID_NOT_FIND_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),SearchBuffer);
  1418.  
  1419.                                                                             ReleaseWindows();
  1420.  
  1421.                                                                             FlushIMsg(BufferWindow);
  1422.  
  1423.                                                                             FoundX = FoundY = 0;
  1424.  
  1425.                                                                             if(MarkedArea)
  1426.                                                                                 MarkArea(-1,-1,-1);
  1427.                                                                         }
  1428.                                                                         else
  1429.                                                                         {
  1430.                                                                             if(LineNumber < CurrentLine)
  1431.                                                                             {
  1432.                                                                                 if(MarkedArea)
  1433.                                                                                     MarkArea(-1,-1,-1);
  1434.  
  1435.                                                                                 DisplayedLines = RedrawScreen(CurrentLine = 0);
  1436.  
  1437.                                                                                 GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1438.                                                                                     GTSC_Top,    CurrentLine,
  1439.                                                                                     GTSC_Total,    Lines,
  1440.                                                                                     GTSC_Visible,    BufLine,
  1441.                                                                                 TAG_DONE);
  1442.                                                                             }
  1443.                                                                             else
  1444.                                                                             {
  1445.                                                                                 if(LineNumber > CurrentLine + DisplayedLines - 1)
  1446.                                                                                 {
  1447.                                                                                     if(MarkedArea)
  1448.                                                                                         MarkArea(-1,-1,-1);
  1449.     
  1450.                                                                                     if(LineNumber >= Lines - BufLine)
  1451.                                                                                     {
  1452.                                                                                         LONG NewCurrentLine;
  1453.  
  1454.                                                                                         if((NewCurrentLine = Lines - BufLine) < 0)
  1455.                                                                                             NewCurrentLine = 0;
  1456.  
  1457.                                                                                         if(CurrentLine != NewCurrentLine)
  1458.                                                                                         {
  1459.                                                                                             DisplayedLines = RedrawScreen(CurrentLine = NewCurrentLine);
  1460.  
  1461.                                                                                             GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1462.                                                                                                 GTSC_Top,    CurrentLine,
  1463.                                                                                                 GTSC_Total,    Lines,
  1464.                                                                                                 GTSC_Visible,    BufLine,
  1465.                                                                                             TAG_DONE);
  1466.                                                                                         }
  1467.                                                                                     }
  1468.                                                                                     else
  1469.                                                                                     {
  1470.                                                                                         DisplayedLines = RedrawScreen(CurrentLine = LineNumber);
  1471.  
  1472.                                                                                         GT_SetGadgetAttrs(GadgetArray[GAD_SCROLL],BufferWindow,NULL,
  1473.                                                                                             GTSC_Top,    CurrentLine,
  1474.                                                                                             GTSC_Total,    Lines,
  1475.                                                                                             GTSC_Visible,    BufLine,
  1476.                                                                                         TAG_DONE);
  1477.                                                                                     }
  1478.                                                                                 }
  1479.                                                                             }
  1480.  
  1481.                                                                             MarkArea(SaveX,LineNumber - CurrentLine,strlen(SearchBuffer));
  1482.                                                                         }
  1483.  
  1484.                                                                         FoundY = (FoundY + 1) % Lines;
  1485.                                                                     }
  1486.                                                                 }
  1487.                                                                 else
  1488.                                                                     MyEasyRequest(BufferWindow,LocaleString(MSG_GLOBAL_NOTHING_IN_THE_BUFFER_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT));
  1489.  
  1490.                                                                 ReleaseWindow(BufferWindow);
  1491.                                                                 break;
  1492.  
  1493.                                                     case MEN_REPEAT:    BlockWindow(BufferWindow);
  1494.  
  1495.                                                                 if(!SearchBuffer[0])
  1496.                                                                     goto GetTheString;
  1497.                                                                 else
  1498.                                                                     goto SearchForIt;
  1499.  
  1500.                                                     case MEN_GOTO:        BumpWindow(TopWindow);
  1501.                                                                 break;
  1502.  
  1503.                                                     case MEN_QUITBUF:
  1504.                                                     case MEN_CLOSEBUF:    BufferTerminated = TRUE;
  1505.                                                                 break;
  1506.  
  1507.                                                     case MEN_CLEARBUF:    if(Lines)
  1508.                                                                 {
  1509.                                                                     BlockWindows();
  1510.  
  1511.                                                                     BlockWindow(BufferWindow);
  1512.  
  1513.                                                                     if(Qualifier & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  1514.                                                                     {
  1515.                                                                         ClearBuffer();
  1516.  
  1517.                                                                         MarkedArea = FALSE;
  1518.  
  1519.                                                                         ReleaseWindow(BufferWindow);
  1520.  
  1521.                                                                         ReleaseWindows();
  1522.  
  1523.                                                                         FlushIMsg(BufferWindow);
  1524.  
  1525.                                                                         goto Restart;
  1526.                                                                     }
  1527.                                                                     else
  1528.                                                                     {
  1529.                                                                         if(MyEasyRequest(BufferWindow,LocaleString(MSG_TERMBUFFER_BUFFER_STILL_HOLDS_LINES_TXT),LocaleString(MSG_GLOBAL_YES_NO_TXT),Lines))
  1530.                                                                         {
  1531.                                                                             ClearBuffer();
  1532.  
  1533.                                                                             MarkedArea = FALSE;
  1534.  
  1535.                                                                             ReleaseWindow(BufferWindow);
  1536.  
  1537.                                                                             ReleaseWindows();
  1538.  
  1539.                                                                             FlushIMsg(BufferWindow);
  1540.  
  1541.                                                                             goto Restart;
  1542.                                                                         }
  1543.                                                                     }
  1544.  
  1545.                                                                     ReleaseWindow(BufferWindow);
  1546.  
  1547.                                                                     ReleaseWindows();
  1548.  
  1549.                                                                     FlushIMsg(BufferWindow);
  1550.                                                                 }
  1551.  
  1552.                                                                 break;
  1553.  
  1554.                                                     default:        break;
  1555.                                                 }
  1556.  
  1557.                                                 Code = MenuItem -> NextSelect;
  1558.                                             }
  1559.                                         }
  1560.                                     }
  1561.                                 }
  1562.  
  1563.                                 RemoveGList(BufferWindow,GadgetList,(UWORD)-1);
  1564.                             }
  1565.  
  1566.                             FreeGadgets(GadgetList);
  1567.  
  1568.                             BumpWindow(TopWindow);
  1569.  
  1570.                             MarkArea(-1,-1,-1);
  1571.  
  1572.                             ScreenToBack(BufferScreen);
  1573.  
  1574.                             BufferWindow -> Flags |= WFLG_RMBTRAP;
  1575.  
  1576.                             ClearMenuStrip(BufferWindow);
  1577.  
  1578.                             CloseWindow(BufferWindow);
  1579.                         }
  1580.                     }
  1581.  
  1582.                     FreeMenus(BufferMenuStrip);
  1583.                 }
  1584.  
  1585.                 FreeVisualInfo(BufferVisualInfo);
  1586.             }
  1587.  
  1588.             CloseScreen(BufferScreen);
  1589.         }
  1590.     }
  1591.  
  1592.     Forbid();
  1593.  
  1594.     BufferProcess = NULL;
  1595.  
  1596.     Signal(ThisProcess,SIGBREAKF_CTRL_C);
  1597. }
  1598.